package com.dongbao.util;

import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;

public class PsiMethodUtil {

    public static PsiMethod findNearestSuperMethod(PsiMethod method, boolean includeInterfaces) {
        if (method == null || method.isConstructor() ) {
            return null;
        }
        final PsiClass psiClass = method.getContainingClass();
        if (psiClass == null) {
            return null;
        }
        final PsiClass superClass = psiClass.getSuperClass();
        if (superClass == null) {
            return null;
        }
        PsiMethod superMethod = findMethodInSuperClass(method, psiClass, superClass);
        if (superMethod == null && includeInterfaces) {
            superMethod = findMethodInInterfaces(method, psiClass, superClass);
        }
        return superMethod;
    }

    private static PsiMethod findMethodInSuperClass(PsiMethod method, PsiClass psiClass, PsiClass superClass) {
        PsiMethod superMethod = superClass.findMethodBySignature(method, false);
        if (superMethod != null && !superMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
            return superMethod;
        }
        superMethod = null;
        final PsiClass[] superInterfaces = superClass.getInterfaces();
        for (PsiClass superInterface : superInterfaces) {
            if (psiClass.isInheritor(superInterface, true)) {
                superMethod = findMethodInSuperClass(method, psiClass, superInterface);
                if (superMethod != null) {
                    break;
                }
            }
        }
        return superMethod;
    }

    private static PsiMethod findMethodInInterfaces(PsiMethod method, PsiClass psiClass, PsiClass superClass) {
        PsiMethod superMethod = null;
        final PsiClass[] superInterfaces = superClass.getInterfaces();
        for (PsiClass superInterface : superInterfaces) {
            if (psiClass.isInheritor(superInterface, true)) {
                superMethod = superInterface.findMethodBySignature(method, false);
                if (superMethod != null && !superMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
                    break;
                }
                superMethod = findMethodInInterfaces(method, psiClass, superInterface);
                if (superMethod != null) {
                    break;
                }
            }
        }
        return superMethod;
    }


}
